package com.chushouya.manager.service.admin.impl;


import com.general.framework.core.lang.*;
import com.chushouya.common.constant.SystemConfigEnum;
import com.chushouya.common.support.Contexts;
import com.chushouya.manager.dao.entity.ConfigEntity;
import com.chushouya.manager.dao.repository.ConfigRepository;
import com.chushouya.manager.dto.admin.config.ConfigDTO;
import com.chushouya.manager.dto.admin.config.ConfigListDTO;
import com.chushouya.manager.dto.admin.config.ConfigQuery;
import com.chushouya.manager.dto.admin.config.ConfigSaveDTO;
import com.chushouya.manager.service.admin.ConfigService;
import com.general.framework.core.constant.Constants;
import com.general.framework.core.exception.Ex;
import com.general.framework.core.schema.PageResult;
import com.general.framework.data.redis.RedisCache;
import lombok.extern.slf4j.Slf4j;
import org.springframework.stereotype.Service;

import javax.annotation.PostConstruct;
import javax.annotation.Resource;
import java.util.Collection;
import java.util.List;
import java.util.Objects;

/**
 * 参数配置
 */
@Service
@Slf4j
public class ConfigServiceImpl implements ConfigService {

    @Resource
    private ConfigRepository configRepository;

    @Resource
    private RedisCache redisCache;

    /**
     * 项目启动时，初始化参数到缓存
     */
    @PostConstruct
    public void init() {
        try {
            log.info("===>开始初始化ConfigService");
            this.intConfigData();
            this.loadConfigCache();
        } catch (Exception e) {
            log.error("===>ConfigService初始化失败", e);
            throw new RuntimeException("ConfigService初始化失败", e);
        }
    }

    @Override
    public ConfigSaveDTO selectConfigById(Long configId) {
        Check.notNull(configId, "configId can not be null");
        return Beans.copy(configRepository.selectByPrimaryKey(configId), ConfigSaveDTO.class);
    }

    @Override
    public ConfigDTO selectConfigByKey(String configKey) {
        ConfigDTO cacheConfig = redisCache.getCacheObject(this.getCacheKey(configKey));
        if (Objects.nonNull(cacheConfig)) {
            return cacheConfig;
        }
        ConfigQuery query = new ConfigQuery();
        query.setConfigKey(configKey);
        ConfigEntity configEntity = configRepository.selectOne(query);
        if (Objects.isNull(configEntity)) {
            throw Ex.business("不存在的系统参数:{}", configKey);

        }
        final ConfigDTO config = Beans.copy(configEntity, ConfigDTO.class);
        redisCache.setCacheObject(this.getCacheKey(configKey), config);
        return config;
    }

    @Override
    public PageResult<ConfigListDTO> selectConfigPageResult(ConfigQuery query) {
        PageResult<ConfigEntity> pageResult = configRepository.selectPageResult(query);
        return PageResult.of(pageResult, ConfigListDTO.class);
    }

    @Override
    public Long addConfig(ConfigSaveDTO config) {
        if (this.checkConfigKeyUnique(config)) {
            throw Ex.business("新增配置'{}'不能与其它重复", config.getConfigKey());
        }
        ConfigEntity configEntity = Beans.copy(config, ConfigEntity.class);
        configEntity.setHandleUser(Contexts.getUserContext().getUserName());
        configEntity.setCreateTime(Dates.getTimeNow());
        configRepository.insertSelective(configEntity);
        redisCache.setCacheObject(getCacheKey(config.getConfigKey()), Beans.copy(configEntity, ConfigDTO.class));
        return configEntity.getConfigId();
    }

    @Override
    public Long editConfig(ConfigSaveDTO config) {
        Check.notNull(config.getConfigId(), "configId can not be null");
        if (this.checkConfigKeyUnique(config)) {
            throw Ex.business("修改配置'{}'不能与其它重复", config.getConfigKey());
        }
        ConfigEntity configEntity = Beans.copy(config, ConfigEntity.class);
        configEntity.setHandleUser(Contexts.getUserContext().getUserName());
        configEntity.setUpdateTime(Dates.getTimeNow());
        configRepository.updateByPrimaryKeySelective(configEntity);
        redisCache.setCacheObject(this.getCacheKey(config.getConfigKey()), Beans.copy(configEntity, ConfigDTO.class));
        return configEntity.getConfigId();
    }

    private boolean checkConfigKeyUnique(ConfigSaveDTO config) {
        ConfigQuery query = new ConfigQuery();
        query.setConfigKey(config.getConfigKey());
        if (Objects.nonNull(config.getConfigId())) {
            query.setIdNotEqualTo(config.getConfigId());
        }
        ConfigEntity configEntity = configRepository.selectOne(query);
        return Objects.nonNull(configEntity);
    }

    @Override
    public void removeConfig(Long configId) {
        Check.notNull(configId, "configId can not be null");
        ConfigEntity configEntity = configRepository.selectByPrimaryKey(configId);
        Check.notNull(configEntity, "配置不存在");
        if (configEntity.getSystemConfig()) {
            throw Ex.business("系统内置参数'{}'不能删除 ", configEntity.getConfigKey());
        }
        configRepository.deleteByPrimaryKey(configId);
        redisCache.deleteObject(this.getCacheKey(configEntity.getConfigKey()));
    }

    @Override
    public void intConfigData() {
        try {
            log.info("===>开始初始化系统配置数据");
            SystemConfigEnum[] configEnums = SystemConfigEnum.values();
            log.info("===>找到{}个系统配置枚举", configEnums.length);
            
            for (SystemConfigEnum configEnum : configEnums) {
                try {
                    ConfigQuery query = new ConfigQuery();
                    query.setConfigKey(configEnum.getConfigKey());
                    ConfigEntity existingConfig = configRepository.selectOne(query);
                    if (Objects.isNull(existingConfig)) {
                        ConfigEntity configEntity = new ConfigEntity();
                        configEntity.setConfigKey(configEnum.getConfigKey());
                        configEntity.setConfigName(configEnum.getConfigName());
                        configEntity.setConfigValue(configEnum.getConfigValue());
                        configEntity.setConfigType(configEnum.getConfigType().value());
                        configEntity.setSystemConfig(Boolean.TRUE);
                        configEntity.setHandleUser("平台系统");
                        configEntity.setCreateTime(Dates.getTimeNow());
                        configEntity.setRemark(configEnum.getRemark());
                        
//                        log.debug("===>插入配置到数据库: {}", configEnum.getConfigKey());
                        configRepository.insertSelective(configEntity);
//                        log.info("===>成功创建配置: {}", configEnum.getConfigKey());
                    } else {
//                        log.debug("===>配置已存在，跳过: {}", configEnum.getConfigKey());
                    }
                } catch (Exception e) {
                    log.error("===>处理配置项失败: {}", configEnum.getConfigKey(), e);
                    throw e;
                }
            }
            log.info("===>系统配置数据初始化完成");
        } catch (Exception e) {
            log.error("===>系统配置数据初始化失败", e);
            throw new RuntimeException("系统配置数据初始化失败", e);
        }
    }
    @Override
    public void loadConfigCache() {
        try {
            log.info("===>开始加载配置缓存");
            List<ConfigEntity> configList = configRepository.selectConfigList(new ConfigQuery());
            log.info("===>从数据库获取到{}个配置项", configList.size());
            
            for (ConfigEntity config : configList) {
                try {
                    // 手动映射替代Beans.copy，避免CGLib初始化问题
                    ConfigDTO configDTO = new ConfigDTO();
                    configDTO.setConfigKey(config.getConfigKey());
                    configDTO.setConfigName(config.getConfigName());
                    configDTO.setConfigType(config.getConfigType());
                    configDTO.setConfigValue(config.getConfigValue());
                    
                    redisCache.setCacheObject(this.getCacheKey(config.getConfigKey()), configDTO);
                } catch (Exception e) {
                    log.error("===>缓存配置失败: {}", config.getConfigKey(), e);
                    throw e;
                }
            }
            log.info("===>配置缓存加载完成");
        } catch (Exception e) {
            log.error("===>加载配置缓存失败", e);
            throw new RuntimeException("加载配置缓存失败", e);
        }
    }

    @Override
    public void clearConfigCache() {
        Collection<String> keys = redisCache.keys(Constants.CACHE_CONFIG_KEY + "*");
        redisCache.deleteObject(keys);
    }

    @Override
    public void resetConfigCache() {
        this.clearConfigCache();
        this.loadConfigCache();
    }

    @Override
    public List<Long> getSuperAdminUserIdList() {
        ConfigDTO cacheConfig = this.selectConfigByKey(SystemConfigEnum.SUPER_ADMIN_ID_LIST.getConfigKey());
        if (Objects.isNull(cacheConfig)) {
            return Lists.emptyList();
        }
        return Strings.splitToLongList(cacheConfig.getConfigValue(), ",");
    }

    /**
     * 设置cache key
     * @param configKey 参数键
     * @return 缓存键key
     */
    private String getCacheKey(String configKey) {
        return Constants.CACHE_CONFIG_KEY + configKey;
    }

    @Override
    public String getStringConfig(String configKey) {
        return this.selectConfigByKey(configKey).getConfigValue();
    }

}
